﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using System.Diagnostics;
using MovingBlocks.Classes;
using System.Windows.Media.Imaging;
using System.Windows.Media;

namespace MovingBlocks
{
    public partial class Game : PhoneApplicationPage
    {
        /* Declarations */
        PhotoBlocksGenerator photoBlocksGenerator;
        List<WriteableBitmap> generatedListOfBlocks;
        List<KeyValuePair<Image, int>> picturesIDs;
        List<KeyValuePair<Image, int>> mixedPicturesIDs;


        private int actualBlankNumber;

        /* Game constructor */ 
        public Game()
        {
            InitializeComponent();

            photoBlocksGenerator = new PhotoBlocksGenerator(InputArgumentsContext.Current.numberOfCols, InputArgumentsContext.Current.numberOfRows);
            generatedListOfBlocks = photoBlocksGenerator.GeneratePhotoList();

            picturesIDs = pushImagePartsToListOfPairs(generatedListOfBlocks, InputArgumentsContext.Current.numberOfRows, InputArgumentsContext.Current.numberOfCols);
            mixedPicturesIDs = pushImagePartsToListOfPairs(generatedListOfBlocks, InputArgumentsContext.Current.numberOfRows, InputArgumentsContext.Current.numberOfCols);

            // Before creating the playground, mixing the photo
            generatedListOfBlocks = MixGeneratedPhotoList(generatedListOfBlocks);

            PreparePlayGround(generatedListOfBlocks, InputArgumentsContext.Current.numberOfRows, InputArgumentsContext.Current.numberOfCols, photoBlocksGenerator.rowsSize, photoBlocksGenerator.colsSize);

            //imageAndSavingTesting();
            //PreparePlayGround(mixedGeneratedListOfBlocks, InputArgumentsContext.Current.numberOfRows, InputArgumentsContext.Current.numberOfCols, photoBlocksGenerator.rowsSize, photoBlocksGenerator.colsSize);
        }


        /* Preparing playground for puzzle game */
        private void PreparePlayGround(List<WriteableBitmap> generatedListOfBlocks, int numberOfRows, int numberOfColumns, int rowSize, int colSize)
        {
            prepareColumnsAndRowsFromGrid(numberOfRows, numberOfColumns);
            if (InputArgumentsContext.Current.numberOfCols != 3)
            {
                deleteRandomPicturePart(generatedListOfBlocks.Count);
            }
            pushImagePartsToGrid(generatedListOfBlocks, numberOfRows, numberOfColumns);

        }


        /* Mixing the generated list of images */
        private List<WriteableBitmap> MixGeneratedPhotoList(List<WriteableBitmap> generatedListOfBlocks)
        {
            Random rng = new Random();
            int n = generatedListOfBlocks.Count;

            if (InputArgumentsContext.Current.numberOfCols == 3)
            {
                deleteRandomPicturePart(generatedListOfBlocks.Count);

                n = 50;
                while (n > 1)
                {
                    
                    n--;
                    int k = rng.Next(0, generatedListOfBlocks.Count);

                    if (actualBlankNumber == k - 1 || actualBlankNumber == k + 1)
                    {
                        WriteableBitmap value = generatedListOfBlocks[k];
                        generatedListOfBlocks[k] = generatedListOfBlocks[actualBlankNumber];
                        generatedListOfBlocks[actualBlankNumber] = value;
                        SwapList(mixedPicturesIDs, k, actualBlankNumber);
                        actualBlankNumber = k;
                    }
                }
            }
            else
            {
                while (n > 1)
                {
                    n--;
                    int k = rng.Next(n + 1);
                    WriteableBitmap value = generatedListOfBlocks[k];
                    generatedListOfBlocks[k] = generatedListOfBlocks[n];
                    generatedListOfBlocks[n] = value;
                    SwapList(mixedPicturesIDs, k, n);
                }
            }
            
            return generatedListOfBlocks;
        }

        /* Swapping the list elements */
        static void SwapList(List<KeyValuePair<Image, int>> list, int indexA, int indexB)
        {
            KeyValuePair<Image, int> tmp = list[indexA];
            list[indexA] = list[indexB];
            list[indexB] = tmp;
        }

        /* Pushing image parts to grid */
        private void pushImagePartsToGrid(List<WriteableBitmap> generatedListOfBlocks, int numberOfRows, int numberOfColumns)
        {
            int imageFromListCounter = 0;

            for (int k = 0; k < numberOfColumns; k++)
            {
                if (imageFromListCounter == generatedListOfBlocks.Count)
                    break;

                for (int l = 0; l < numberOfRows; l++)
                {
                    Image genericPicturePart = new Image();
                    genericPicturePart.Source = generatedListOfBlocks[imageFromListCounter];
                    PlayPanel.Children.Add(genericPicturePart);
                    genericPicturePart.SetValue(Grid.ColumnProperty, k);
                    genericPicturePart.SetValue(Grid.RowProperty, l);
                    genericPicturePart.Tap += genericPicturePart_Tap;
                    imageFromListCounter += 1;
                }
            }
            PlayPanel.ShowGridLines = true;
        }

        private List<KeyValuePair<Image, int>> pushImagePartsToListOfPairs(List<WriteableBitmap> generatedListOfBlocks, int numberOfRows, int numberOfColumns)
        {
            List<KeyValuePair<Image, int>> pictures = new List<KeyValuePair<Image, int>>();

            int imageFromListCounter = 0;
            for (int k = 0; k < numberOfColumns; k++)
            {
                if (imageFromListCounter == generatedListOfBlocks.Count)
                    break;
                for (int l = 0; l < numberOfRows; l++)
                {
                    Image genericPicturePart = new Image();
                    genericPicturePart.Source = generatedListOfBlocks[imageFromListCounter];
                    pictures.Insert(imageFromListCounter, new KeyValuePair<Image, int>(genericPicturePart, imageFromListCounter));
                    imageFromListCounter += 1;
                }
            }
            return pictures;
        }


        /* Columns and Rows in Grid preparation */
        private void prepareColumnsAndRowsFromGrid(int numberOfRows, int numberOfColumns)
        {
            PlayPanel.Width = System.Windows.Application.Current.Host.Content.ActualWidth;
            PlayPanel.Height = 0.75 * System.Windows.Application.Current.Host.Content.ActualWidth;

            for (int i = 0; i < numberOfColumns; i++)
            {
                PlayPanel.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(PlayPanel.Width / numberOfColumns) });
            }

            for (int i = 0; i < numberOfRows; i++)
            {
                PlayPanel.RowDefinitions.Add(new RowDefinition { Height = new GridLength(PlayPanel.Height / numberOfRows) });
            }
        }


        /* Tap Action on grid elements*/
        void genericPicturePart_Tap(object sender, System.Windows.Input.GestureEventArgs e)
        {
            try
            {
                Image temp = new Image();
                Image sendImage = sender as Image;
                //MessageBox.Show("mixed " + mixedArrayOfIDs[PlayPanel.Children.IndexOf(sendImage)].ToString() 
                //    + " \n" + picturesIDs[0].Key.ToString() + ' ' + picturesIDs[0].Value.ToString()
                //    + " \n" + picturesIDs[1].Key.ToString() + ' ' + picturesIDs[1].Value.ToString()
                //    + " \n" + picturesIDs[2].Key.ToString() + ' ' + picturesIDs[2].Value.ToString()
                //    + " \n" + picturesIDs[3].Key.ToString() + ' ' + picturesIDs[3].Value.ToString()
                //    + " \n" + picturesIDs[4].Key.ToString() + ' ' + picturesIDs[4].Value.ToString()
                //    );
                
                //  -----   Old code
                //MessageBox.Show(PlayPanel.Children.Count.ToString());
                //sendImage.SetValue(Grid.ColumnProperty, 0);
                //sendImage.SetValue(Grid.RowProperty, 0);
                //Point gridPosition = e.GetPosition(null);
                //MessageBox.Show(PlayPanel.Children.IndexOf(sendImage).ToString() + ' ' + picturesIDs[0].Value.ToString());
                //MessageBox.Show(PlayPanel.Children.IndexOf(sendImage).ToString() + ' ' + picturesIDs[PlayPanel.Children.IndexOf(sendImage)]);
                //PlayPanel.Children.RemoveAt(actualBlankNumber);
                //PlayPanel.Children.Insert(actualBlankNumber, sendImage);
                //PlayPanel.Children.RemoveAt(PlayPanel.Children.IndexOf(sendImage));
                //PlayPanel.Children.Remove(PlayPanel.Children.IndexOf(sendImage);//, randomImage());
                //actualBlankNumber = PlayPanel.Children.IndexOf(sendImage);
                //PlayPanel.Children.RemoveAt(0);
                //sendImage.SetValue(Grid.ColumnProperty, 0);
                //sendImage.SetValue(Grid.RowProperty, 0);

                //sendImage.Tap += genericPicturePart_Tap;
                //picturesIDs[0];
                //PlayPanel.Children.

                if (isNeightbour(actualBlankNumber, PlayPanel.Children.IndexOf(sendImage))) 
                {
                    WriteableBitmap tempWrBitmap = new WriteableBitmap(photoBlocksGenerator.colsSize, photoBlocksGenerator.rowsSize);
                    WriteableBitmap blankWrBitmap = new WriteableBitmap(photoBlocksGenerator.colsSize, photoBlocksGenerator.rowsSize);

                    tempWrBitmap = this.generatedListOfBlocks[PlayPanel.Children.IndexOf(sendImage)];
                    this.generatedListOfBlocks[actualBlankNumber] = tempWrBitmap;

                    SwapList(this.mixedPicturesIDs, actualBlankNumber, PlayPanel.Children.IndexOf(sendImage));

                    actualBlankNumber = PlayPanel.Children.IndexOf(sendImage);
                    this.generatedListOfBlocks[PlayPanel.Children.IndexOf(sendImage)] = blankWrBitmap;

                    PlayPanel.Children.Clear();

                    pushImagePartsToGrid(this.generatedListOfBlocks, InputArgumentsContext.Current.numberOfRows, InputArgumentsContext.Current.numberOfCols);

                    if (isWinMove())
                    {
                        Image winImage = new Image();
                        winImage.Source = InputArgumentsContext.Current.Image;
                        
                        PlayPanel.Children.Clear();
                        
                        PlayPanel.RowDefinitions.Clear();
                        PlayPanel.ColumnDefinitions.Clear();
                        PlayPanel.Children.Add(winImage);
                        
                        MessageBox.Show("WIIIIN!!!!");
                    }
                }
            }
            catch
            {
                MessageBox.Show("Something is wrong...");
            }
        }

        /* Checks is movement of block is win move*/
        private bool isWinMove()
        {
            int correctPicturePositionCounter = 0;
            
            for (int i = 0; i < this.mixedPicturesIDs.Count(); i++)
            {
                if (mixedPicturesIDs[i].Value == i)
                {
                    correctPicturePositionCounter++;
                }
            }
            
            if (correctPicturePositionCounter == mixedPicturesIDs.Count)
            {
                return true;
            }
            else
            {
                return false;
            }

        }

        
        /* Checks is neightbour of tapped block is blank block */
        private bool isNeightbour(int actualBlankNumber, int indexOfImagePart)
        {
            if (actualBlankNumber == indexOfImagePart + 1 || actualBlankNumber == indexOfImagePart - 1 
                || actualBlankNumber == indexOfImagePart + InputArgumentsContext.Current.numberOfCols
                || actualBlankNumber == indexOfImagePart - InputArgumentsContext.Current.numberOfCols)
            {
                return true;
            }
            else
            {
                return false;
            }
        }


        /* Deleting random element from grid by pushing the blank grid */
        private void deleteRandomPicturePart(int imagePartsCount)
        {
            int randomIndex;
            Random rnd = new Random();
            randomIndex = rnd.Next(imagePartsCount);
            WriteableBitmap blankWrBitmap = new WriteableBitmap(photoBlocksGenerator.colsSize, photoBlocksGenerator.rowsSize);
            generatedListOfBlocks[randomIndex] = blankWrBitmap;

            this.actualBlankNumber = randomIndex;
        }


        /* --------------------------------------------------------------------- OLD CODE ---------------------------------------------------------------------  */

        /* Checks is the current of blank part is location on border or not*/
        private bool isNotNBorder(int actualBlankNumber, int indexOfImagePart)
        {
            if (indexOfImagePart % InputArgumentsContext.Current.numberOfCols == 0
                && (Math.Abs((actualBlankNumber % InputArgumentsContext.Current.numberOfCols) - InputArgumentsContext.Current.numberOfCols) == 1
                || (actualBlankNumber % InputArgumentsContext.Current.numberOfCols == 1)))
            {
                return false;
            }
            else
            {
                return true;
            }
        }

        private UIElement randomImage()
        {
            Image blankImage = new Image();
            BitmapImage bi3 = new BitmapImage();
            bi3.UriSource = new Uri("blank.png", UriKind.Relative);
            blankImage.Source = bi3;
            blankImage.Width = photoBlocksGenerator.colsSize;
            blankImage.Height = photoBlocksGenerator.rowsSize;
            return blankImage;
        }



        /* Save image to testing (parts) */
        private void imageAndSavingTesting()
        {
            Image testImage1 = new Image();
            testImage1.Source = InputArgumentsContext.Current.Image;
         
            // testing the generator
            MessageBox.Show("You have chosen the image" + generatedListOfBlocks[1].ToString());
            generatedListOfBlocks[0].SaveToMediaLibrary("myImage.jpg");
            testImage1.Source = generatedListOfBlocks[2];
        }
    }
}